<?php

namespace App\Http\Controllers;

use App\Jobs\GdGeoJob;
use App\Jobs\GeocoderJob;
use App\Jobs\TransferJob;
use App\Models\EpsLngLat;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

/**
 * Class EpsLngLatController
 * @package App\Http\Controllers
 * create_at: 2025-09-09 08:52:08
 * update_at: 2025-09-09 08:52:08
 */
class EpsLngLatController extends Controller
{
//    const KEY = "bdf76598848741e8e1b120de02b4bf44";
    const KEY = "a74e30a83b4b3e53ac26a8ef7f382aad";
    const GD_KEY = "2a2314daef7a9866c0a5246ee3fc7b30";
    const API_URL = "http://api.tianditu.gov.cn/geocoder";
    const GD_API_URL = "https://restapi.amap.com/v3/geocode/geo";
    const ON_QUEUE = "geocoder";
    const GD_ON_QUEUE = "gd_geo";
    const TRANSFER_ON_QUEUE = "transfer";

    /**
     * 天地图地理编码
     * create_at: 2025-01-11 08:43:14
     * update_at: 2025-01-11 08:43:14
     */
    public function run()
    {
        EpsLngLat::where(["lng_lat_mark" => 3, "disable_mark" => 2])->whereBetween("id", [1, 1500000])->select(["id"])->chunk(100, function (Collection $eps) {
//            $batch = [];
//            foreach ($eps as $ep) {
//                $batch[] = $ep->id;
//            }
//            GeocoderJob::dispatch($batch)->onQueue(self::ON_QUEUE);

            foreach ($eps as $ep) {
                GeocoderJob::dispatch($ep->id)->onQueue(self::ON_QUEUE);
            }
//            $this->handleJob($batch);
        });
    }

    /**
     * 高德地理编码
     * create_at: 2025-01-11 08:43:14
     * update_at: 2025-01-11 08:43:14
     */
    public function runGdGeo()
    {
        EpsLngLat::where(["lng_lat_mark" => 3, "disable_mark" => 2])->whereBetween("id", [1, 1500000])->select(["id"])->chunk(100, function (Collection $eps) {
            foreach ($eps as $ep) {
                GdGeoJob::dispatch($ep->id)->onQueue(self::GD_ON_QUEUE);
            }
        });
    }

    /**
     * 批量转移
     * create_at: 2025-09-20 08:56:16
     * update_at: 2025-09-20 08:56:16
     */
    public function runTransfer()
    {
        EpsLngLat::where(["disable_mark" => 2, "lng_lat_mark" => 1])->orderBy("ent_guid", "asc")->chunk(10000, function (Collection $eps) {
            foreach ($eps as $ep) {
                TransferJob::dispatch($ep)->onQueue(self::TRANSFER_ON_QUEUE);
            }
        });
    }

    /**
     * 生成GUID
     * create_at: 2025-09-09 15:49:28
     * update_at: 2025-09-09 15:49:28
     */
    public function genGuid()
    {
        EpsLngLat::whereNull('ent_guid')->select(["id"])->orderBy("id", "asc")->chunk(100, function (Collection $eps) {
            $now = now();
            Log::info("[{$now}] proccessing:" . $eps->first()->id . " ~ " . $eps->last()->id);
            echo "[$now] proccessing:" . $eps->first()->id . " ~ " . $eps->last()->id . "\n";
            foreach ($eps as $ep) {
                DB::table("eps_lng_lat")->where(["id" => $ep->id])->whereNull("ent_guid")->update(["ent_guid" => $this->create_guid()]);
            }
        });
    }

    /**
     * 单条记录处理 - 天地图
     * @param $id
     * @throws \Illuminate\Http\Client\ConnectionException
     * create_at: 2025-09-09 11:07:23
     * update_at: 2025-09-09 11:07:23
     */
    public function handleJob($id)
    {
//        Log::info("[{$ids}] start");
        $eps = EpsLngLat::select(["id", "registered_address", "latest_annual_report_address", "lng_lat_mark"])->find($id);
        if (empty($eps)) {
            return;
        }

        $address = mb_substr($eps->registered_address, 0, 49);

//        if (!empty($eps->registered_address) && '-' != $eps->latest_annual_report_address) {
//            $address = $eps->latest_annual_report_address;
//        } else {
//            $address = $eps->registered_address;
//        }

        // 如果地址为空，则跳过
        if (empty($address) || '-' == $address) {
            $this->markExcp($eps->id);
            return;
        }

        // 请求
        $response = Http::retry(0)->connectTimeout(2)->timeout(2)->withQueryParameters([
            'tk' => self::KEY,
            'ds' => json_encode([
                "keyWord" => $address
            ], JSON_UNESCAPED_UNICODE)
        ])->post(self::API_URL);

        if ($response->ok()) {
            $res = $response->json();
            if (isset($res["status"]) && 0 == $res["status"] && "ok" == $res["msg"]) {
                $geo = $res['location'];

                DB::table("eps_lng_lat")->where(["id" => $id])->update([
                    "lng" => $geo['lon'],
                    "lat" => $geo['lat'],
                    "lng_lat_mark" => 1,
                    "lng_lat_src" => 1 // 天地图
                ]);
            } else {
                $this->markExcp($eps->id);
            }
        } else {
            $this->markExcp($eps->id);
        }


//        $valid = [];
//        $eps = EpsLngLat::select(["id", "city_sid", "registered_address", "latest_annual_report_address", "lng_lat_mark"])->whereIn('id', $ids)->get()->toArray();
//        if (empty($eps)) {
//            return;
//        }
//
//        foreach ($eps as $ep) {
//            if (1 == $ep['lng_lat_mark']) {
//                continue;
//            }
//
//            if (empty($ep['registered_address']) || '-' == $ep['registered_address']) {
//                $this->markExcp($ep['id']);
//                continue;
//            }
//
//            $valid[] = $ep;
//        }
//
//        if (empty($valid)) {
//            return;
//        }
//
//        $responses = Http::retry(0)->connectTimeout(3)->timeout(3)->pool(function (Pool $pool) use ($valid) {
//            $reqs = [];
//            foreach ($valid as $item) {
//                $reqs[] = $pool->withQueryParameters([
//                    'tk' => self::KEY,
//                    'ds' => json_encode([
//                        "keyWord" => $item['registered_address']
//                    ], JSON_UNESCAPED_UNICODE)
//                ])->post(self::API_URL);
//            }
//            return $reqs;
//        });
//
//        foreach ($responses as $k => $resp) {
//            if ($resp->ok()) {
//                $res = $resp->json();
//
//                if (isset($res["status"]) && 0 == $res["status"] && "ok" == strtolower($res["msg"])) {
//
//                    $geo = $res['location'];
//
//                    DB::table("eps_lng_lat")->where(["id" => $valid[$k]['id']])->update([
//                        "lng" => $geo['lon'],
//                        "lat" => $geo['lat'],
//                        "lng_lat_mark" => 1,
//                        "lng_lat_src" => 1 // 天地图
//                    ]);
//                } else {
//                    $this->markExcp($valid[$k]['id']);
//                }
//            }
//        }

    }

    /**
     * 单条记录处理 - 高德
     * @param $id
     * @throws \Illuminate\Http\Client\ConnectionException
     * create_at: 2025-09-09 11:07:23
     * update_at: 2025-09-09 11:07:23
     */
    public function handleGdJob($id)
    {
        $eps = EpsLngLat::select(["id", "city_sid", "registered_address", "latest_annual_report_address", "lng_lat_mark"])->find($id);
        if (!$eps || 1 == $eps->lng_lat_mark) {
            return;
        }

        $address = $eps->registered_address;

//        if (!empty($eps->latest_annual_report_address) && '-' != $eps->latest_annual_report_address) {
//            $address = $eps->latest_annual_report_address;
//        } else {
//            $address = $eps->registered_address;
//        }

        // 如果地址为空，则跳过
        if (empty($address) || '-' == $address) {
            $this->markExcp($eps->id);
            return;
        }

        // 请求
        $response = Http::retry(0)->connectTimeout(2)->timeout(2)->withQueryParameters([
            'key' => self::GD_KEY,
            'address' => $address,
            'city' => $eps->city_sid,
        ])->get(self::GD_API_URL);

        if ($response->ok()) {
            $res = $response->json();
            if (isset($res["status"]) && 1 == $res["status"] && "ok" == strtolower($res["info"])) {

                $geo = $res['geocodes'][0]['location'];
                $geoArr = explode(",", $geo);

                DB::table("eps_lng_lat")->where(["id" => $eps->id])->update([
                    "lng" => $geoArr[0],
                    "lat" => $geoArr[1],
                    "lng_lat_mark" => 1,
                    "lng_lat_src" => 2 // 高德
                ]);
            } else {
                $this->markExcp($eps->id);
            }
        }
    }

    /**
     * 转移
     * @param $eps
     * create_at: 2025-09-20 09:08:29
     * update_at: 2025-09-20 09:08:29
     */
    public function handleJobTransferJob($eps)
    {
        // 映射
        // 1-从原表中转移 2-固定值 3-需函数处理
        $map = [
            "ent_guid" => ["type" => 1, "rela_key" => "ent_guid"],
            "ent_name" => ["type" => 1, "rela_key" => "ent_name"],
            "add_time" => ["type" => 1, "rela_key" => "created_at"],
            "edit_time" => ["type" => 1, "rela_key" => "updated_at"],
            "ent_status" => ["type" => 1, "rela_key" => "ent_status"],
            "ent_type" => ["type" => 1, "rela_key" => "ent_type"],
            "reg_date" => ["type" => 1, "rela_key" => "establish_date"],
            "ent_faren" => ["type" => 1, "rela_key" => "ent_legal_person"],
            "ent_regcode" => ["type" => 1, "rela_key" => "unified_social_credit_code"],
            "currency_type" => ["type" => 2, "val" => "万(元)"],
            "ent_capital" => ["type" => 1, "rela_key" => "reg_capital_val"],
            "ent_addr" => ["type" => 3, "func" => function ($eps) {
                return (!empty($eps->registered_address) && '-' != $eps->registered_address) ? $eps->registered_address : $eps->latest_annual_report_address;
            }],
            "reg_number" => ["type" => 1, "rela_key" => "registration_number"],
            "org_code" => ["type" => 1, "rela_key" => "organization_code"],
            "linkman" => ["type" => 2, "val" => "-"],
            "linkman_mobile" => ["type" => 1, "rela_key" => "tel"],
            "email" => ["type" => 1, "rela_key" => "email"],
            "ent_range" => ["type" => 1, "rela_key" => "business_scope"],
            "ent_jd" => ["type" => 1, "rela_key" => "lng"],
            "ent_wd" => ["type" => 1, "rela_key" => "lat"],
            "province_id" => ["type" => 1, "rela_key" => "province_id"],
            "province" => ["type" => 1, "rela_key" => "province"],
            "city_id" => ["type" => 1, "rela_key" => "city_id"],
            "city" => ["type" => 1, "rela_key" => "city"],
            "district_id" => ["type" => 1, "rela_key" => "district_id"],
            "district" => ["type" => 1, "rela_key" => "district"],
            "website" => ["type" => 1, "rela_key" => "website"],
            "industry" => ["type" => 1, "rela_key" => "industry"],
            "number_people" => ["type" => 3, "func" => function ($eps) {
                return (int)$eps->insured_number;
            }],
            "approved_date" => ["type" => 3, "func" => function ($eps) {
                return (!empty($eps->approved_date) && '-' != $eps->approved_date) ? $eps->approved_date : null;
            }],
            "more_email" => ["type" => 1, "rela_key" => "more_email"],
            "more_tel" => ["type" => 1, "rela_key" => "more_tel"],
            "ent_grade" => ["type" => 2, "val" => 60],
            "source" => ["type" => 2, "val" => "aqc"],
            "entlabel" => ["type" => 2, "val" => ""],
            "md5_str" => ["type" => 1, "rela_key" => "md5_str"],
        ];

        DB::transaction(function () use ($eps, $map) {
            $item = [];
            foreach ($map as $k => $v) {
                switch ($v["type"]) {
                    case 1:
                        $item[$k] = $eps->{$v["rela_key"]};
                        break;
                    case 2:
                        $item[$k] = $v["val"];
                        break;
                    case 3:
                        $item[$k] = $v["func"]($eps);
                        break;
                }
            }

            DB::table("enterprise")->insertOrIgnore($item);
            DB::table("eps_lng_lat")->where("id", $eps->id)->update(["transfer_mark" => 1]);
        });

//        EpsLngLat::where(["disable_mark" => 2, "transfer_mark" => 2])->where("id", "<", 1000)->chunk(100, function (Collection $eps) use ($map) {
//            DB::transaction(function () use ($eps, $map) {
//                $collects = $eps->all();
//                $batch = [];
//                $ids = [];
//                foreach ($collects as $collect) {
//                    $item = [];
//                    $ids[] = $collect->id;
//                    foreach ($map as $k => $v) {
//                        switch ($v["type"]) {
//                            case 1:
//                                $item[$k] = $collect->{$v["rela_key"]};
//                                break;
//                            case 2:
//                                $item[$k] = $v["val"];
//                                break;
//                            case 3:
//                                $item[$k] = $v["func"]($collect);
//                                break;
//                        }
//                    }
//                    $batch[] = $item;
//                }
//
//                if (!empty($batch)) {
//                    DB::table("enterprise")->insert($batch);
//                    DB::table("eps_lng_lat")->whereIn("id", $ids)->update(["transfer_mark" => 1]);
//                }
//            });
//        });
    }

    /**
     * 生成GUID
     * @return string
     * create_at: 2024-12-20 16:15:45
     * update_at: 2024-12-20 16:15:45
     */
    protected function create_guid()
    {
        if (function_exists('com_create_guid') === true) {
            return trim(com_create_guid(), '{}');
        }

        return strtolower(
            sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535))
        );
    }

    /**
     * markExcp
     * @param $id
     * create_at: 2025-09-09 11:10:00
     * update_at: 2025-09-09 11:10:00
     */
    protected function markExcp($id)
    {
        DB::table("eps_lng_lat")->where(["id" => $id])->update([
            "lng_lat_mark" => 3
        ]);
    }
}
